/**
* MinimaxTreeParser.java
* @author J.T. Gralka <gralkajt@washjeff.edu>, Topher Witt <wittcm19@uww.edu>
* @version 07/09/11
*
* Parses a string into a Minimax Tree
*/

package exe.minimax;

public class MinimaxTreeParser{
 	// ivars	
	private String input; // Contains the String to be converted into a tree
	private int index; // Contains the value of the current index of input being parsed
	private MinimaxTree tree; // Contains the current representation of the tree
	
	// Constructors
	public MinimaxTreeParser(String input){
		this.input = input;
		index = 0;
		tree = new MinimaxTree();
		try{
			parseTree();
		}catch(Exception e){e.printStackTrace();}
		tree.updateNodeTypes(true);
	}
	
	// Accessors
	public MinimaxTree getTree(){
		return tree;
	}

	// Helper methods
	private MinimaxNode parseTree() throws Exception{
		String token = parseToken(index); // Parses the current token
		int nodesToExpand = 0; // Denotes the number of nodes to expand
		MinimaxNode thisNode = new MinimaxNode(); // Creates the current node (value = -1)
		
		// If we're starting from the beginning of the tree...
		if(index == 0){
			// Set the root of the tree to this node
			tree.setRoot(thisNode);
		}
		
		index+=token.length();

		// If the token denotes a subtree...		
		if(token.charAt(0) == '#'){
			// Parse the token's string to determine the # of nodes
			if ( (nodesToExpand = Integer.parseInt(token.substring(1, token.length()))) < 0)
				throw new Exception("MinimaxTreeParser cannot parse a node with a negative number of children.");
			// While there are still nodes to expand...
			while(nodesToExpand > 0){
				// Add a child to the node:			
					// thisNode will be the child's parent
					// recurse, passing a reference to thisNode (it's parent)
				try{
					tree.addChild(thisNode, parseTree());
				}catch(Exception e){e.printStackTrace();}
				// Decrement nodesToExpand value by 1
				nodesToExpand--;
			}	
		}
		
		// Else, if the token denotes a terminal node
		else if(token.charAt(0) == '$'){
			// Set the value of the node to the value provided by the token
			thisNode.setValue(Integer.parseInt(token.substring(1, token.length())));
			// Update the node to represent it's being a leaf			
			thisNode.setIsLeaf(true);
		}
		
		// Return thisNode
		return thisNode;
	}

	public String parseToken(int start){
		int end = start+1;
		while(end < input.length() && input.charAt(end) != '#' && input.charAt(end) != '$'){
			end++;
		}
		return input.substring(start, end);
	}

	public int numTokens(){
		String token = "";
		int letters = 0, tokens = 0;
		while(letters < input.length()-1){		
			token = parseToken(letters);
			letters += token.length();			
			tokens++;
		}
		return tokens;	
	}
	
	public String toString(){
		return input;
	}
}
